using RBAC.Domain.SmartHealthcare.Hosiptial;
using RBAC.Interstructrue;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;

namespace SmartHealthcare.Read.Api.Services
{
    /// <summary>
    /// 药品费用计算服务
    /// </summary>
    public class MedicineCostCalculationService
    {
        private readonly RBACDbContext _dbContext;
        private readonly ILogger<MedicineCostCalculationService> _logger;

        public MedicineCostCalculationService(RBACDbContext dbContext, ILogger<MedicineCostCalculationService> logger)
        {
            _dbContext = dbContext;
            _logger = logger;
        }

        /// <summary>
        /// 计算单个药品费用
        /// </summary>
        /// <param name="medicineId">药品ID</param>
        /// <param name="quantity">数量</param>
        /// <param name="insuranceRatio">医保报销比例（0-100，默认0）</param>
        /// <returns>药品费用计算结果</returns>
        public async Task<MedicineCostResult> CalculateSingleMedicineCostAsync(long medicineId, int quantity, decimal insuranceRatio = 0)
        {
            try
            {
                _logger.LogInformation($"开始计算药品费用，药品ID：{medicineId}，数量：{quantity}，医保比例：{insuranceRatio}%");

                // 查询药品信息
                var medicine = await _dbContext.medicines
                    .Where(x => x.Id == medicineId && !x.IsDeleted)
                    .FirstOrDefaultAsync();

                if (medicine == null)
                {
                    _logger.LogWarning($"药品不存在或已删除，ID：{medicineId}");
                    return new MedicineCostResult
                    {
                        Success = false,
                        ErrorMessage = $"药品不存在或已删除，ID：{medicineId}"
                    };
                }

                // 检查库存
                if (medicine.Inventory < quantity)
                {
                    _logger.LogWarning($"药品库存不足，药品：{medicine.MedicineName}，需要：{quantity}，库存：{medicine.Inventory}");
                    return new MedicineCostResult
                    {
                        Success = false,
                        ErrorMessage = $"药品库存不足，药品：{medicine.MedicineName}，需要：{quantity}，库存：{medicine.Inventory}"
                    };
                }

                // 计算费用
                var unitPrice = medicine.Price;
                var totalAmount = unitPrice * quantity;
                var insuranceAmount = totalAmount * (insuranceRatio / 100);
                var selfPayAmount = totalAmount - insuranceAmount;

                var result = new MedicineCostResult
                {
                    Success = true,
                    MedicineId = medicineId,
                    MedicineName = medicine.MedicineName,
                    Specification = medicine.Specification,
                    UnitPrice = unitPrice,
                    Quantity = quantity,
                    TotalAmount = totalAmount,
                    InsuranceRatio = insuranceRatio,
                    InsuranceAmount = insuranceAmount,
                    SelfPayAmount = selfPayAmount,
                    CostName = medicine.CostName,
                    DrugType = medicine.DrugType
                };

                _logger.LogInformation($"药品费用计算完成，药品：{medicine.MedicineName}，总金额：{totalAmount:C2}，医保报销：{insuranceAmount:C2}，自费：{selfPayAmount:C2}");

                return result;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"计算药品费用时发生错误，药品ID：{medicineId}");
                return new MedicineCostResult
                {
                    Success = false,
                    ErrorMessage = $"计算药品费用时发生错误：{ex.Message}"
                };
            }
        }

        /// <summary>
        /// 计算多个药品的总费用
        /// </summary>
        /// <param name="medicineItems">药品项目列表</param>
        /// <param name="insuranceRatio">医保报销比例（0-100，默认0）</param>
        /// <returns>药品费用计算结果</returns>
        public async Task<MedicineCostResult> CalculateMultipleMedicineCostAsync(List<MedicineCostItem> medicineItems, decimal insuranceRatio = 0)
        {
            try
            {
                _logger.LogInformation($"开始计算多个药品费用，药品数量：{medicineItems.Count}，医保比例：{insuranceRatio}%");

                var results = new List<MedicineCostResult>();
                var totalAmount = 0m;
                var totalInsuranceAmount = 0m;
                var totalSelfPayAmount = 0m;

                foreach (var item in medicineItems)
                {
                    var result = await CalculateSingleMedicineCostAsync(item.MedicineId, item.Quantity, insuranceRatio);
                    if (!result.Success)
                    {
                        return result; // 返回第一个错误
                    }

                    results.Add(result);
                    totalAmount += result.TotalAmount;
                    totalInsuranceAmount += result.InsuranceAmount;
                    totalSelfPayAmount += result.SelfPayAmount;
                }

                var finalResult = new MedicineCostResult
                {
                    Success = true,
                    TotalAmount = totalAmount,
                    InsuranceRatio = insuranceRatio,
                    InsuranceAmount = totalInsuranceAmount,
                    SelfPayAmount = totalSelfPayAmount,
                    MedicineDetails = results
                };

                _logger.LogInformation($"多个药品费用计算完成，总金额：{totalAmount:C2}，医保报销：{totalInsuranceAmount:C2}，自费：{totalSelfPayAmount:C2}");

                return finalResult;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "计算多个药品费用时发生错误");
                return new MedicineCostResult
                {
                    Success = false,
                    ErrorMessage = $"计算多个药品费用时发生错误：{ex.Message}"
                };
            }
        }

        /// <summary>
        /// 根据药品名称搜索并计算费用
        /// </summary>
        /// <param name="medicineName">药品名称（支持模糊搜索）</param>
        /// <param name="quantity">数量</param>
        /// <param name="insuranceRatio">医保报销比例（0-100，默认0）</param>
        /// <returns>药品费用计算结果列表</returns>
        public async Task<List<MedicineCostResult>> CalculateMedicineCostByNameAsync(string medicineName, int quantity, decimal insuranceRatio = 0)
        {
            try
            {
                _logger.LogInformation($"根据药品名称搜索并计算费用，药品名称：{medicineName}，数量：{quantity}，医保比例：{insuranceRatio}%");

                // 查询匹配的药品
                var medicines = await _dbContext.medicines
                    .Where(x => x.MedicineName.Contains(medicineName) && !x.IsDeleted)
                    .ToListAsync();

                if (!medicines.Any())
                {
                    _logger.LogWarning($"未找到匹配的药品，名称：{medicineName}");
                    return new List<MedicineCostResult>
                    {
                        new MedicineCostResult
                        {
                            Success = false,
                            ErrorMessage = $"未找到匹配的药品，名称：{medicineName}"
                        }
                    };
                }

                var results = new List<MedicineCostResult>();

                foreach (var medicine in medicines)
                {
                    var result = await CalculateSingleMedicineCostAsync(medicine.Id, quantity, insuranceRatio);
                    results.Add(result);
                }

                _logger.LogInformation($"根据药品名称搜索并计算费用完成，找到{medicines.Count}个匹配药品");

                return results;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"根据药品名称搜索并计算费用时发生错误，药品名称：{medicineName}");
                return new List<MedicineCostResult>
                {
                    new MedicineCostResult
                    {
                        Success = false,
                        ErrorMessage = $"根据药品名称搜索并计算费用时发生错误：{ex.Message}"
                    }
                };
            }
        }

        /// <summary>
        /// 计算患者所有药品费用
        /// </summary>
        /// <param name="medicalCard">病人卡号</param>
        /// <param name="startDate">开始日期（可选）</param>
        /// <param name="endDate">结束日期（可选）</param>
        /// <returns>患者药品费用统计结果</returns>
        public async Task<PatientMedicineCostResult> CalculatePatientMedicineCostAsync(string medicalCard, DateTime? startDate = null, DateTime? endDate = null)
        {
            try
            {
                _logger.LogInformation($"开始计算患者药品费用，病人卡号：{medicalCard}，时间范围：{startDate?.ToString("yyyy-MM-dd")} 至 {endDate?.ToString("yyyy-MM-dd")}");

                // 查询患者的药品费用记录
                var query = _dbContext.hospitalExpenses
                    .Where(x => x.MedicalCard == medicalCard && x.ItemType == "药品" && !x.IsDeleted);

                if (startDate.HasValue)
                {
                    query = query.Where(x => x.ExpenseTime >= startDate.Value);
                }

                if (endDate.HasValue)
                {
                    query = query.Where(x => x.ExpenseTime <= endDate.Value);
                }

                var expenses = await query.ToListAsync();

                if (!expenses.Any())
                {
                    _logger.LogInformation($"患者{medicalCard}在指定时间范围内没有药品费用记录");
                    return new PatientMedicineCostResult
                    {
                        Success = true,
                        MedicalCard = medicalCard,
                        TotalAmount = 0,
                        TotalInsuranceAmount = 0,
                        TotalSelfPayAmount = 0,
                        MedicineCount = 0,
                        ExpenseDetails = new List<MedicineCostResult>()
                    };
                }

                var totalAmount = expenses.Sum(x => x.TotalAmount);
                var totalInsuranceAmount = expenses.Sum(x => x.InsuranceAmount);
                var totalSelfPayAmount = expenses.Sum(x => x.SelfPayAmount);

                var expenseDetails = expenses.Select(x => new MedicineCostResult
                {
                    Success = true,
                    MedicineId = x.ItemId ?? 0,
                    MedicineName = x.ItemName,
                    Specification = x.Specification,
                    UnitPrice = x.UnitPrice,
                    Quantity = x.Quantity,
                    TotalAmount = x.TotalAmount,
                    InsuranceRatio = x.InsuranceRatio,
                    InsuranceAmount = x.InsuranceAmount,
                    SelfPayAmount = x.SelfPayAmount,
                    ExpenseTime = x.ExpenseTime
                }).ToList();

                var result = new PatientMedicineCostResult
                {
                    Success = true,
                    MedicalCard = medicalCard,
                    TotalAmount = totalAmount,
                    TotalInsuranceAmount = totalInsuranceAmount,
                    TotalSelfPayAmount = totalSelfPayAmount,
                    MedicineCount = expenses.Count,
                    ExpenseDetails = expenseDetails,
                    StartDate = startDate,
                    EndDate = endDate
                };

                _logger.LogInformation($"患者药品费用计算完成，病人卡号：{medicalCard}，总金额：{totalAmount:C2}，医保报销：{totalInsuranceAmount:C2}，自费：{totalSelfPayAmount:C2}");

                return result;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"计算患者药品费用时发生错误，病人卡号：{medicalCard}");
                return new PatientMedicineCostResult
                {
                    Success = false,
                    ErrorMessage = $"计算患者药品费用时发生错误：{ex.Message}"
                };
            }
        }

        /// <summary>
        /// 验证药品价格是否合理
        /// </summary>
        /// <param name="medicineId">药品ID</param>
        /// <param name="unitPrice">单价</param>
        /// <returns>验证结果</returns>
        public async Task<PriceValidationResult> ValidateMedicinePriceAsync(long medicineId, decimal unitPrice)
        {
            try
            {
                var medicine = await _dbContext.medicines
                    .Where(x => x.Id == medicineId && !x.IsDeleted)
                    .FirstOrDefaultAsync();

                if (medicine == null)
                {
                    return new PriceValidationResult
                    {
                        IsValid = false,
                        ErrorMessage = $"药品不存在或已删除，ID：{medicineId}"
                    };
                }

                // 检查价格是否在合理范围内（进价的50%-200%）
                var minPrice = medicine.PurchasePrice * 0.5m;
                var maxPrice = medicine.PurchasePrice * 2.0m;

                var isValid = unitPrice >= minPrice && unitPrice <= maxPrice;

                return new PriceValidationResult
                {
                    IsValid = isValid,
                    MedicineName = medicine.MedicineName,
                    PurchasePrice = medicine.PurchasePrice,
                    CurrentPrice = medicine.Price,
                    SuggestedMinPrice = minPrice,
                    SuggestedMaxPrice = maxPrice,
                    ErrorMessage = isValid ? null : $"价格{unitPrice:C2}不在合理范围内（{minPrice:C2} - {maxPrice:C2}）"
                };
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"验证药品价格时发生错误，药品ID：{medicineId}");
                return new PriceValidationResult
                {
                    IsValid = false,
                    ErrorMessage = $"验证药品价格时发生错误：{ex.Message}"
                };
            }
        }
    }

    /// <summary>
    /// 药品费用计算结果
    /// </summary>
    public class MedicineCostResult
    {
        /// <summary>
        /// 是否成功
        /// </summary>
        public bool Success { get; set; }

        /// <summary>
        /// 错误信息
        /// </summary>
        public string ErrorMessage { get; set; }

        /// <summary>
        /// 药品ID
        /// </summary>
        public long MedicineId { get; set; }

        /// <summary>
        /// 药品名称
        /// </summary>
        public string MedicineName { get; set; }

        /// <summary>
        /// 规格
        /// </summary>
        public string Specification { get; set; }

        /// <summary>
        /// 单价
        /// </summary>
        public decimal UnitPrice { get; set; }

        /// <summary>
        /// 数量
        /// </summary>
        public int Quantity { get; set; }

        /// <summary>
        /// 总金额
        /// </summary>
        public decimal TotalAmount { get; set; }

        /// <summary>
        /// 医保报销比例
        /// </summary>
        public decimal InsuranceRatio { get; set; }

        /// <summary>
        /// 医保报销金额
        /// </summary>
        public decimal InsuranceAmount { get; set; }

        /// <summary>
        /// 自费金额
        /// </summary>
        public decimal SelfPayAmount { get; set; }

        /// <summary>
        /// 费用名称
        /// </summary>
        public string CostName { get; set; }

        /// <summary>
        /// 药品类型
        /// </summary>
        public string DrugType { get; set; }

        /// <summary>
        /// 费用时间
        /// </summary>
        public DateTime? ExpenseTime { get; set; }

        /// <summary>
        /// 药品明细（用于批量计算）
        /// </summary>
        public List<MedicineCostResult> MedicineDetails { get; set; } = new List<MedicineCostResult>();
    }

    /// <summary>
    /// 药品费用项目
    /// </summary>
    public class MedicineCostItem
    {
        /// <summary>
        /// 药品ID
        /// </summary>
        public long MedicineId { get; set; }

        /// <summary>
        /// 数量
        /// </summary>
        public int Quantity { get; set; }
    }

    /// <summary>
    /// 患者药品费用统计结果
    /// </summary>
    public class PatientMedicineCostResult
    {
        /// <summary>
        /// 是否成功
        /// </summary>
        public bool Success { get; set; }

        /// <summary>
        /// 错误信息
        /// </summary>
        public string ErrorMessage { get; set; }

        /// <summary>
        /// 病人卡号
        /// </summary>
        public string MedicalCard { get; set; }

        /// <summary>
        /// 总金额
        /// </summary>
        public decimal TotalAmount { get; set; }

        /// <summary>
        /// 总医保报销金额
        /// </summary>
        public decimal TotalInsuranceAmount { get; set; }

        /// <summary>
        /// 总自费金额
        /// </summary>
        public decimal TotalSelfPayAmount { get; set; }

        /// <summary>
        /// 药品数量
        /// </summary>
        public int MedicineCount { get; set; }

        /// <summary>
        /// 费用明细
        /// </summary>
        public List<MedicineCostResult> ExpenseDetails { get; set; } = new List<MedicineCostResult>();

        /// <summary>
        /// 开始日期
        /// </summary>
        public DateTime? StartDate { get; set; }

        /// <summary>
        /// 结束日期
        /// </summary>
        public DateTime? EndDate { get; set; }
    }

    /// <summary>
    /// 价格验证结果
    /// </summary>
    public class PriceValidationResult
    {
        /// <summary>
        /// 是否有效
        /// </summary>
        public bool IsValid { get; set; }

        /// <summary>
        /// 错误信息
        /// </summary>
        public string ErrorMessage { get; set; }

        /// <summary>
        /// 药品名称
        /// </summary>
        public string MedicineName { get; set; }

        /// <summary>
        /// 进价
        /// </summary>
        public decimal PurchasePrice { get; set; }

        /// <summary>
        /// 当前价格
        /// </summary>
        public decimal CurrentPrice { get; set; }

        /// <summary>
        /// 建议最低价格
        /// </summary>
        public decimal SuggestedMinPrice { get; set; }

        /// <summary>
        /// 建议最高价格
        /// </summary>
        public decimal SuggestedMaxPrice { get; set; }
    }
} 